package org.xenon.vote.controller;

import org.springframework.web.bind.annotation.*;
import org.xenon.vote.exception.BallotExistException;
import org.xenon.vote.listener.OnlineJudgeListener;
import org.xenon.vote.model.pojo.po.Choice;
import org.xenon.vote.model.pojo.po.Judge;
import org.xenon.vote.model.pojo.po.Turn;
import org.xenon.vote.model.pojo.vo.Result;
import org.xenon.vote.service.*;
import org.xenon.vote.util.Converter;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/turn")
public class TurnController {
    private final TurnService turnService;
    private final JudgeService judgeService;
    private final ChoiceService choiceService;
    private final BallotService ballotService;
    private final BallotManager manager;

    public TurnController(TurnService turnService, JudgeService judgeService,
                          ChoiceService choiceService, BallotService ballotService, BallotManager manager) {
        this.turnService = turnService;
        this.judgeService = judgeService;
        this.choiceService = choiceService;
        this.ballotService = ballotService;
        this.manager = manager;
    }

    /**
     * 获取投票信息或者准备状态
     * @param id 投票的ID
     */
    @GetMapping("/prepare")
    public Result prepare(int id, HttpServletRequest req) {
        //记录一个选项
        class Cho{
            String detail;
            int score;

            public Cho(String detail, int score) {
                this.detail = detail;
                this.score = score;
            }

            public String getDetail() {
                return detail;
            }

            public void setDetail(String detail) {
                this.detail = detail;
            }

            public int getScore() {
                return score;
            }

            public void setScore(int score) {
                this.score = score;
            }
        }
        //记录一个轮次
        class Lun{
            final List<Cho> choices;
            final List<String> judge;
            final int id;
            final int order;
            public Lun(HashMap<String, Integer> choices, List<String> judge, int id, int order) {
                List<Cho> chos = new ArrayList<>();
                for (String s : choices.keySet())
                    chos.add(new Cho(s, choices.get(s)));
                this.choices = chos;
                this.judge = judge;
                this.id = id;
                this.order = order;
            }

            public List<Cho> getChoices() {
                return choices;
            }

            public List<String> getJudge() {
                return judge;
            }

            public int getId() {
                return id;
            }

            public int getOrder() {
                return order;
            }
        }
        //记录要返回的结果
        class Res{
            final List<String> presented;
            final List<Lun> turn;
            final String name;

            public List<Lun> getTurn() {
                return turn;
            }

            public Res(List<String> presented, List<Lun> turn, String name) {
                this.presented = presented;
                this.turn = turn;
                this.name = name;
            }

            public List<String> getPresented() {
                return presented;
            }

            public String getName() {
                return name;
            }
        }
        String mail = (String) req.getSession().getAttribute("user");
        if (!ballotService.checkByBallot(id, mail))
            return new Result(false, "login");
        List<Turn> turns = turnService.getAll(id);
        List<Lun> luns = new ArrayList<>();
        for (Turn t : turns)
            luns.add(new Lun(choiceService.getResult(t.getId()),
                    Converter.judgeToString(judgeService.get(t.getId())), t.getId(), t.getOrder()));
        List<String> presented = new ArrayList<>();
        List<Judge> judges = OnlineJudgeListener.getOnline(mail);
        for (Judge j : judges)
            if(j.getTurn() == turns.get(turns.size()-1).getId()) presented.add(j.getName());
        return new Result(true, new Res(presented, luns, ballotService.getName(id)));
    }

    /**
     * 测试是否在投票中
     * @param id 投票的ID 其实目前没用上 仅做账户验证
     */
    @GetMapping("/isReady")
    public Result isReady(HttpServletRequest req) {
        String mail = (String) req.getSession().getAttribute("user");
        return new Result(manager.check(mail), "");
    }

    /**
     * 停止投票 系统会预创建下一轮投票 下一轮开始时只需要传入裁判数据, 选出人数, 裁判选择数就可以开始
     * @param id 投票ID
     */
    @PostMapping("/stop")
    public Result stop(int id, HttpServletRequest req){
        String mail = (String) req.getSession().getAttribute("user");
        Turn turn = turnService.add(id, 0, 0);
        HashMap<Choice, Integer> result = manager.stop(mail, id);
        if (result == null || !ballotService.checkByBallot(id, mail))
            return new Result(false, "login");
        int newTurnId = turn.getId();
        return new Result(true, newTurnId);
    }

    /**
     * 创建下一场投票, 紧接着上一轮的结果
     * 必须要用户没有正在进行的投票才能操作
     * @param id 投票的ID
     * @param judge 下一轮的裁判名单
     * @param limit 选出的人数
     */
    @PostMapping("/next")
    public Result next(int id, String judge, int limit, int option, HttpServletRequest req){
        String mail = (String) req.getSession().getAttribute("user");
        if(!ballotService.checkByBallot(id, mail)) return new Result(false, "login");//权限验证
        if(manager.check(mail)) return new Result(false, "underway"); //是否在运行, 在运行则拒绝
        Turn turn = turnService.getLast(id); //获得新的轮次
        turn.setLimit(limit);
        turn.setOption(option);
        turnService.update(turn);//修改轮次信息
        //judgeService.clear(turn.getId());
        judgeService.add(Converter.toJudgeMapNameOnly(judge, judgeService, mail), turn.getId(), mail); //添加裁判
        return new Result(true, turn.getId());
    }

    /**
     * 开启新一轮投票
     * @param id 投票的ID
     */
    @PostMapping("/start")
    public Result start(int id, HttpServletRequest req){
        String mail = (String) req.getSession().getAttribute("user");
        try {
            manager.add(turnService.getLast(id), mail);
        } catch (BallotExistException e) {
            return new Result(false, "exist");
        }
        return new Result(true, id);
    }
}
